package orchestration.android.execution.tasks;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import orchestration.android.parcelable.ParcelableAndroidTaskDTO;
import orchestration.android.parcelable.ParcelableProperty;
import orchestration.businessprocess.model.BPAnnotation;
import orchestration.persistence.exceptions.MalformedAnnotationException;
import orchestration.utils.AnnotationUtils;
import android.content.Intent;
import android.net.Uri;

public class AndroidTaskFactory {
	
	public static AndroidTask createAndroidTask(ParcelableAndroidTaskDTO dto) throws MalformedAnnotationException{
		String id= dto.getTaskId();
		HashMap<String, ParcelableProperty> input= dto.getInputProperties();
		HashMap<String, ParcelableProperty> output= dto.getOutputProperties();
		HashMap<String, BPAnnotation> source2AnnotationMap = AnnotationUtils.getSource2AnnotationMap(dto.getAnnotations());
		String taskType= AnnotationUtils.getAndroidTaskType(source2AnnotationMap);
		AndroidTask task=null;
		//create the task
		if(taskType.equals(AnnotationUtils.ANDROID_INFO_TASK_TYPE_ACTIVITY)){
			task= createActivityTask(id, source2AnnotationMap, input, output);
		}else if(taskType.equals(AnnotationUtils.ANDROID_INFO_TASK_TYPE_START_SERVICE)){
			task= createServiceStartStopTask(id, source2AnnotationMap,input,true);
		}else if(taskType.equals(AnnotationUtils.ANDROID_INFO_TASK_TYPE_STOP_SERVICE)){
			task= createServiceStartStopTask(id, source2AnnotationMap,input,false);
		}else if(taskType.equals(AnnotationUtils.ANDROID_INFO_TASK_TYPE_BIND_SERVICE)){
			task= createServiceBinderTask(id, source2AnnotationMap,input, output);
		}else if(taskType.equals(AnnotationUtils.ANDROID_INFO_TASK_TYPE_QUERY_CONTENT_PROVIDER)){
			task= createContentProviderTask(id,source2AnnotationMap,input,output);
		}
		//create mappings
		String mappingsString= AnnotationUtils.getTaskMappings(source2AnnotationMap);
		if(mappingsString!=null && mappingsString!=""){
			Map<String, String> mappings = AnnotationUtils.readMappings(mappingsString);
			task.setMappings(mappings);
		}
		return task;
	}
	
	public static ContentProviderQueryTask createContentProviderTask(String id,Map<String, BPAnnotation> source2AnnotationMap,
			HashMap<String,ParcelableProperty> input, HashMap<String,ParcelableProperty> output) {
		ContentProviderQueryTask cpt= new ContentProviderQueryTask(id);
		Uri uri=Uri.parse(AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_URI));
		String[] projection=AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_PROJECTION).split(";");
		String where=AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_WHERE_CLAUSE);
		String[] whereArgs=AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_WHERE_ARGS).split(" ");
		String order= AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_ORDER);
		cpt.setInput(input);
		cpt.setOutput(output);
		cpt.setUri(uri);
		cpt.setProjection(projection);
		cpt.setWhereClause(where);
		cpt.setWhereArgs(whereArgs);
		cpt.setOrder(order);
		String[] saveOps= AnnotationUtils.getContentProviderDetail(source2AnnotationMap, AnnotationUtils.CONTENT_PROVIDER_SAVE_OPERATION).split(";");
		for(String operationString : saveOps){
			String opOut=null;
			String opName;
			String[] params=null;
			int outputEndCharPos=operationString.indexOf("=");
			opOut=operationString.substring(0, outputEndCharPos);
			int startParamsIndex=operationString.indexOf("(");
			opName= operationString.substring(outputEndCharPos+1,startParamsIndex);
			String paramsSubstring = operationString.substring(startParamsIndex+1, operationString.indexOf(")"));
			if(paramsSubstring!=""){
				params=paramsSubstring.split(",");
			}
			SaveQueryResultOperation operation= createSaveQueryResultOperation(opName, params, opOut);
			cpt.addOperation(operation);
		}
		return cpt;
	}

	public static ActivityTask createActivityTask(String id,Map<String, BPAnnotation> source2AnnotationMap, HashMap<String,ParcelableProperty> input, HashMap<String,ParcelableProperty> output) throws MalformedAnnotationException{
		ActivityTask at= new ActivityTask(id);
		Intent intent= AnnotationUtils.getIntent(source2AnnotationMap);
		String ignoreBackString= source2AnnotationMap.get(AnnotationUtils.ANDROID_INFO_SOURCE).getDetail(AnnotationUtils.ANDROID_INFO_IGNORE_BACK);
		boolean ignoreBack= ignoreBackString!=null && !ignoreBackString.equals("");
		at.setInput(input);
		at.setOutput(output);
		at.setIntent(intent);
		at.setIgnoreBack(ignoreBack);
		return at;
	}
	public static ServiceStartStopTask createServiceStartStopTask(String id,Map<String, BPAnnotation> source2AnnotationMap,HashMap<String,ParcelableProperty> input,boolean start) throws MalformedAnnotationException{
		ServiceStartStopTask sst= new ServiceStartStopTask(id);
		Intent intent= AnnotationUtils.getIntent(source2AnnotationMap);
		sst.setInput(input);
		sst.setIntent(intent);
		sst.setStart(start);
		return sst;
	}
	public static ServiceBinderTask createServiceBinderTask(String id,Map<String, BPAnnotation> source2AnnotationMap,HashMap<String,ParcelableProperty> input, HashMap<String,ParcelableProperty> output) throws MalformedAnnotationException{
		ServiceBinderTask sbt = new ServiceBinderTask(id);
		sbt.setAidl(AnnotationUtils.getAidlFile(source2AnnotationMap));
		sbt.setIntent(AnnotationUtils.getIntent(source2AnnotationMap));
		String[] operationsToCall = AnnotationUtils.getOperationsToCall(source2AnnotationMap);
		if(operationsToCall!=null){
			for(String operation : operationsToCall){
				operation=operation.trim();
				//read opOutput
				String opOut=null;
				String opName;
				String[] paramsFields=null;
				int outputEndCharPos=operation.indexOf("=");
				if(outputEndCharPos!=-1){
					opOut=operation.substring(0, outputEndCharPos);
				}
				//read opName
				int startParamsIndex=operation.indexOf("(");
				opName= operation.substring(outputEndCharPos+1,startParamsIndex).trim();
				//read param names
				int endParamsIndex = operation.indexOf(")");
				if(startParamsIndex+1!=endParamsIndex){
					paramsFields=operation.substring(startParamsIndex+1, endParamsIndex).split(",");
				}
				sbt.createOperation(opName,opOut,paramsFields);
			}
		}
		return sbt;
	}
	

	public static AndroidTask createBroadcastTask(ParcelableAndroidTaskDTO dto) throws MalformedAnnotationException {
		String id=dto.getTaskId();
		HashMap<String,BPAnnotation> source2AnnotationMap= AnnotationUtils.getSource2AnnotationMap(dto.getAnnotations());
		boolean sendBroadcast= AnnotationUtils.isThrowing(source2AnnotationMap);
		if(sendBroadcast){
			return createSendBroadcastTask(id,source2AnnotationMap,dto.getInputProperties());
		}else{
			return createReceiveBroadcastTask(id,source2AnnotationMap,dto.getOutputProperties());
		}
	}
	public static SendBroadcastTask createSendBroadcastTask(String id,Map<String, BPAnnotation> source2AnnotationMap,HashMap<String, ParcelableProperty> input) throws MalformedAnnotationException{
		SendBroadcastTask sbct= new SendBroadcastTask(id);
		sbct.setInput(input);
		sbct.setIntent(AnnotationUtils.getIntent(source2AnnotationMap));
		return sbct;
	}
	public static ReceiveBroadcastTask createReceiveBroadcastTask(String id,Map<String, BPAnnotation> source2AnnotationMap,HashMap<String, ParcelableProperty> output){
		ReceiveBroadcastTask rbct= new ReceiveBroadcastTask(id);
		rbct.setOutput(output);
//		sbct.se(AnnotationUtils.getIntent(source2AnnotationMap));
		return rbct;
	}
	
	public static ServiceOperation createServiceOperation(int opCode,String aidl_name,List<String> inputId,String outputId){
		ServiceOperation so= new ServiceOperation();
		so.setInputId(inputId);
		so.setOutputId(outputId);
		so.setOpCode(opCode);
		return so;
	}
	public static SaveQueryResultOperation createSaveQueryResultOperation(String operation, String[] params,String outputName){
		SaveQueryResultOperation sqro = new SaveQueryResultOperation();
		sqro.setOperation(operation);
		sqro.setParams(params);
		sqro.setOutputName(outputName);
		return sqro;
	}

	public static StartProcessTask createStartProcessTask(ParcelableAndroidTaskDTO dto) {
		StartProcessTask task= new StartProcessTask(dto.getTaskId());
		task.setOutput(dto.getOutputProperties());
		return task;
	}
	public static EndProcessTask createEndProcessTask(ParcelableAndroidTaskDTO dto) {
		EndProcessTask task= new EndProcessTask(dto.getTaskId());
		task.setInput(dto.getInputProperties());
		return task;
	}
}
